﻿namespace OneWorks.Utils.Upload
{
    using System;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Web;

    /// <summary>
    /// Web文件上传简单处理
    /// </summary>
    public class FileUploadHandler
    {
        private readonly HttpPostedFileBase _baseFile;

        public FileUploadHandler(HttpPostedFileBase baseFile)
        {
            if (_baseFile == null)
                throw new ArgumentNullException("baseFile");
            _baseFile = baseFile;
        }

        /// <summary>
        /// 文件后缀验证
        /// </summary>
        /// <param name="regexp">例如:jpg|jpeg|bmp|gif</param>
        /// <returns>true:验证通过,false:格式不正确</returns>
        private bool VerifySuffix(string regexp)
        {
            if (regexp.IndexOf('|') == -1) throw new ArgumentException("验证文件类型表达式格式不正确");
            string regExp = string.Format(@"^.*?\.({0})$", regexp);
            var suffix = GetFileSuffix();
            return !string.IsNullOrEmpty(suffix) && Regex.IsMatch(suffix, regExp);
        }

        /// <summary>
        /// 获取文件后缀名,包含"."
        /// </summary>
        /// <returns></returns>
        private string GetFileSuffix()
        {
            return Path.GetExtension(_baseFile.FileName);
        }

        /// <summary>
        /// 文件夹目录处理
        /// </summary>
        /// <param name="path"></param>
        private static void DirectoryProcess(string path)
        {
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
        }

        /// <summary>
        /// 保存上传文件,设置文件格式
        /// </summary>
        /// <param name="suffixs">例如:jpg|jpeg|bmp|gif </param>
        /// <returns></returns>
        public string Save(string suffixs)
        {
            return Save(null, null, null, suffixs);
        }

        /// <summary>
        /// 保存上传文件,设置上传文件名称
        /// 默认路径为System.IO.Directory.GetCurrentDirectory()
        /// </summary>
        /// <param name="getNameFunc">设置上传文件名称方法</param>
        public string Save(Func<string> getNameFunc)
        {
            return Save(null, null, getNameFunc);
        }

        /// <summary>
        /// 保存上传文件,设置上传文件名称和文件格式
        /// 默认路径为System.IO.Directory.GetCurrentDirectory()
        /// </summary>
        /// <param name="suffixs"> </param>
        /// <param name="getNameFunc">设置上传文件名称方法</param>
        public string Save(string suffixs, Func<string> getNameFunc)
        {
            return Save(null, null, getNameFunc, suffixs);
        }

        /// <summary>
        /// 保存上传文件,设置上传文件名称,路径为HttpContext.MapPath
        /// </summary>
        /// <param name="httpContext">当前请求处理的上下文对象</param>
        /// <param name="virtualPath">虚拟目录</param>
        /// <param name="getNameFunc">获取上传文件名称</param>
        /// <param name="suffixs">例如:jpg|jpeg|bmp|gif </param>   
        /// <param name="exceptionFun">异常处理 </param>
        /// <returns></returns>
        public string Save(HttpContext httpContext, string virtualPath, Func<string> getNameFunc = null, string suffixs = "txt|docx|doc|jpg|jpeg|bmp|gif|xlsx|xls", Action<Exception> exceptionFun = null)
        {
            try
            {
                string suffix = GetFileSuffix();

                if (!VerifySuffix(suffixs)) throw new ArgumentException("文件格式不正确");

                string path;

                if (httpContext == null || string.IsNullOrEmpty(virtualPath))
                    path = Directory.GetCurrentDirectory();
                else
                    path = httpContext.Server.MapPath(virtualPath);

                string fileName = getNameFunc == null ? Guid.NewGuid().ToString() : getNameFunc();

                if (string.IsNullOrEmpty(fileName)) throw new ArgumentException("设置上传文件名方法错误");

                string fullFileName = path + fileName + suffix;
                DirectoryProcess(path);
                _baseFile.SaveAs(fullFileName);                
                return fullFileName;
            }
            catch (Exception exception)
            {
                if (exceptionFun != null)
                    exceptionFun(exception);
                return "";
            }
        }
    }
}
